package ch7.DiningPhilosophers;

/**
 * 支持死锁恢复的AbstractPhilosopher子类
 */

import ch3.Singleton.CASBasedCounter;
import ch7.DiningPhilosophers.BuggyLckBasedPhilosopher;
import ch7.DiningPhilosophers.Chopstick;
import util.Debug;

import java.util.concurrent.locks.ReentrantLock;

public class RecoverablePhilosopher extends BuggyLckBasedPhilosopher {

    public RecoverablePhilosopher(int id, Chopstick left, Chopstick right) {
        super(id, left, right);
    }

    @Override
    protected boolean pickUpChopstick(Chopstick chopstick) {
       final ReentrantLock lock = LOCK_MAP.get(chopstick);
        try {
            lock.lockInterruptibly();
        } catch (InterruptedException e) {
            // 接受到中断信号时，使当前线程释放已经持有的锁
            Debug.info("%s detected interrupt.", Thread.currentThread().getName());
            Chopstick theOtherChopstick = chopstick == left ? right : left;
            theOtherChopstick.putDown();
            LOCK_MAP.get(theOtherChopstick).unlock();
            return false;
        }
        try {
            Debug.info("%s is picking up %s on his %s...%n", this, chopstick, chopstick==left ? "left" : "right");
            chopstick.pickUp();
        } catch (Exception e) {
            e.printStackTrace();
            lock.unlock();
            return false;
        }
        return true;
    }
}
